package cn.pupil.springframework.context.annotation;

import cn.hutool.core.util.StrUtil;
import cn.pupil.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import cn.pupil.springframework.beans.factory.config.BeanDefinition;
import cn.pupil.springframework.beans.factory.support.BeanDefinitionRegistry;
import cn.pupil.springframework.context.stereotype.Component;

import java.util.Set;

/**
 * @Description: 对象扫描装具体处理类
 * @Author: pupil
 * @Date: 2024/11/24 下午 5:42
 */
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

    private BeanDefinitionRegistry registry;

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }

    /**
     * 执行扫描
     * 扫描获取类信息、Bean的作用域和类名
     *
     * @param basePackages
     */
    public void doScan(String... basePackages) {
        for (String basePackage : basePackages) {
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition beanDefinition : candidates) {
                // 解析 Bean 的作用域 singleton、prototype
                String beanScope = resolveBeanScope(beanDefinition);
                if (StrUtil.isNotEmpty(beanScope)) {
                    beanDefinition.setScope(beanScope);
                }
                registry.registerBeanDefinition(determineBeanName(beanDefinition), beanDefinition);
            }
        }

        // 注册处理注解的 BeanPostProcessor（@Autowired、@Value）
        registry.registerBeanDefinition("cn.pupil.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor",new BeanDefinition(AutowiredAnnotationBeanPostProcessor.class));
    }

    /**
     * 解析获取Bean的作用域
     *
     * @param beanDefinition
     * @return
     */
    private String resolveBeanScope(BeanDefinition beanDefinition) {
        // 通过bean的定义获取beanClass
        Class<?> beanClass = beanDefinition.getBeanClass();
        // 通过beanClass获取Scope注释
        Scope scope = beanClass.getAnnotation(Scope.class);
        // 注释不为空，从注释取出Bean的作用域
        if (null != scope) return scope.value();
        // 注释为空，返回空字符串
        return StrUtil.EMPTY;
    }

    /**
     * 解析获取Bean名
     *
     * @param beanDefinition
     * @return
     */
    private String determineBeanName(BeanDefinition beanDefinition) {
        // 通过bean的定义获取beanClass
        Class<?> beanClass = beanDefinition.getBeanClass();
        // 通过beanClass获取Component注释
        Component component = beanClass.getAnnotation(Component.class);
        // 从注释取出beanName
        String beanName = component.value();
        // 如果beanName为空，通过class获取简单的类全限定名
        if (StrUtil.isEmpty(beanName)) {
            beanName = StrUtil.lowerFirst(beanClass.getSimpleName());
        }
        return beanName;
    }
}
